import {
  App,
  Inject,
  Logger,
  Provide,
  Scope,
  ScopeEnum,
} from '@midwayjs/decorator';
import { BaseService } from '@cool-midway/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
import { TaskInfoEntity } from '../entity/info';
import { TaskLogEntity } from '../entity/log';
import { DoupiaopiaoTblistEntity } from '../../doupiaopiao/entity/tborder';
import { DoupiaopiaoOrderEntity } from '../../doupiaopiao/entity/order';
import { DoupiaopiaoUserEntity } from '../../doupiaopiao/entity/user';
import { DoupiaopiaoSettingEntity } from '../../doupiaopiao/entity/setting';
import { DoupiaopiaoCarmiEntity } from '../../doupiaopiao/entity/carmi';

import { ILogger } from '@midwayjs/logger';
import * as _ from 'lodash';
import { Utils } from '../../../comm/utils';
import { TaskInfoQueue } from '../queue/task';
import { IMidwayApplication } from '@midwayjs/core';
import moment = require('moment');
import { TaoBaoRequestService } from '../config';
import { MangoOrderService } from '../../mango/service/order';

/**
 * 任务
 */
@Provide()
@Scope(ScopeEnum.Request, { allowDowngrade: true })
export class TaskInfoService extends BaseService {
  @InjectEntityModel(TaskInfoEntity)
  taskInfoEntity: Repository<TaskInfoEntity>;

  @Logger()
  logger: ILogger;

  @InjectEntityModel(TaskLogEntity)
  taskLogEntity: Repository<TaskLogEntity>;

  @Inject()
  taskInfoQueue: TaskInfoQueue;
  @Inject()
  mangoOrderService: MangoOrderService;
  @App()
  app: IMidwayApplication;

  @Inject()
  utils: Utils;
  @Inject()
  taoBaoRequestService: TaoBaoRequestService;

  @InjectEntityModel(DoupiaopiaoOrderEntity)
  doupiaopiaoOrderEntity: Repository<DoupiaopiaoOrderEntity>;
  @InjectEntityModel(DoupiaopiaoTblistEntity)
  doupiaopiaoTblistEntity: Repository<DoupiaopiaoTblistEntity>;
  @InjectEntityModel(DoupiaopiaoUserEntity)
  doupiaopiaoUserEntity: Repository<DoupiaopiaoUserEntity>;
  @InjectEntityModel(DoupiaopiaoSettingEntity)
  doupiaopiaoSettingEntity: Repository<DoupiaopiaoSettingEntity>;
  @InjectEntityModel(DoupiaopiaoCarmiEntity)
  doupiaopiaoCarmiEntity: Repository<DoupiaopiaoCarmiEntity>;
  /**
   * 停止任务
   * @param id
   */
  async stop(id) {
    const task = await this.taskInfoEntity.findOneBy({ id });
    if (task) {
      const result = await this.taskInfoQueue.getRepeatableJobs();
      const job = _.find(result, { id: task.id + '' });
      if (job) {
        await this.taskInfoQueue.removeRepeatableByKey(job.key);
      }
      task.status = 0;
      await this.taskInfoEntity.update(task.id, task);
      await this.updateNextRunTime(task.id);
    }
  }

  /**
   * 移除任务
   * @param taskId
   */
  async remove(taskId) {
    const result = await this.taskInfoQueue.getRepeatableJobs();
    const job = _.find(result, { id: taskId + '' });
    await this.taskInfoQueue.removeRepeatableByKey(job.key);
  }

  /**
   * 开始任务
   * @param id
   * @param type
   */
  async start(id, type?) {
    const task = await this.taskInfoEntity.findOneBy({ id });
    task.status = 1;
    if (type || type == 0) {
      task.type = type;
    }
    await this.addOrUpdate(task);
  }

  /**
   * 手动执行一次
   * @param id
   */
  async once(id) {
    const task = await this.taskInfoEntity.findOneBy({ id });
    if (task) {
      await this.taskInfoQueue.add(
        {
          ...task,
          isOnce: true,
        },
        {
          jobId: task.id.toString(),
          removeOnComplete: true,
          removeOnFail: true,
        }
      );
    }
  }

  /**
   * 检查任务是否存在
   * @param jobId
   */
  async exist(jobId) {
    const result = await this.taskInfoQueue.getRepeatableJobs();
    const ids = result.map(e => {
      return e.id;
    });
    return ids.includes(jobId.toString());
  }

  /**
   * 新增或修改
   * @param params
   */
  async addOrUpdate(params) {
    delete params.repeatCount;
    let repeatConf;
    await this.getOrmManager().transaction(async transactionalEntityManager => {
      if (params.taskType === 0) {
        params.limit = null;
        params.every = null;
      } else {
        params.cron = null;
      }
      await transactionalEntityManager.save(TaskInfoEntity, params);

      if (params.status === 1) {
        const exist = await this.exist(params.id);
        if (exist) {
          await this.remove(params.id);
        }
        const { every, limit, startDate, endDate, cron } = params;
        const repeat = {
          every,
          limit,
          jobId: params.id,
          startDate,
          endDate,
          cron,
        };
        await this.utils.removeEmptyP(repeat);
        const result = await this.taskInfoQueue.add(params, {
          jobId: params.id,
          removeOnComplete: true,
          removeOnFail: true,
          repeat,
        });
        if (!result) {
          throw new Error('任务添加失败，请检查任务配置');
        }
        // await transactionalEntityManager.update(TaskInfoEntity, params.id, {
        //   jobId: params.id,
        //   type: params.type,
        // });
        repeatConf = result.opts;
      }
    });
    if (params.status === 1) {
      this.utils.sleep(1000);
      await this.updateNextRunTime(params.id);
      await this.nativeQuery(
        'update task_info a set a.repeatConf = ? where a.id = ?',
        [JSON.stringify(repeatConf.repeat), params.id]
      );
    }
  }

  /**
   * 删除
   * @param ids
   */
  async delete(ids) {
    let idArr;
    if (ids instanceof Array) {
      idArr = ids;
    } else {
      idArr = ids.split(',');
    }
    for (const id of idArr) {
      const task = await this.taskInfoEntity.findOneBy({ id });
      const exist = await this.exist(task.id);
      if (exist) {
        this.stop(task.id);
      }
      await this.taskInfoEntity.delete({ id });
      await this.taskLogEntity.delete({ taskId: id });
    }
  }

  /**
   * 任务日志
   * @param query
   */
  async log(query) {
    const { id, status } = query;
    return await this.sqlRenderPage(
      `
      SELECT
          a.*,
          b.NAME AS taskName
      FROM
      task_log a
      JOIN task_info b ON a.taskId = b.id
      where 1=1
      ${this.setSql(id, 'and a.taskId = ?', [id])}
      ${this.setSql(status, 'and a.status = ?', [status])}
      `,
      query
    );
  }

  /**
   * 保存任务记录，成功任务每个任务保留最新20条日志，失败日志不会删除
   * @param task
   * @param status
   * @param detail
   */
  async record(task, status, detail?) {
    await this.taskLogEntity.save({
      taskId: task.id,
      status,
      detail: detail || '',
    });
    await this.nativeQuery(
      `DELETE a
      FROM
      task_log a,
          ( SELECT id FROM task_log where taskId = ? AND status = 1 ORDER BY id DESC LIMIT ?, 1 ) b
      WHERE
      a.taskId = ? AND
      a.status = 1 AND
      a.id < b.id`,
      [task.id, 19, task.id]
    ); // 日志保留最新的20条
  }

  /**
   * 初始化任务
   */
  async initTask() {
    setInterval(async () => {
      this.logger.info('init task....');
      const runningTasks = await this.taskInfoEntity.findBy({ status: 1 });
      if (!_.isEmpty(runningTasks)) {
        for (const task of runningTasks) {
          const job = await this.exist(task.id); // 任务已存在就不添加
          if (!job) {
            this.logger.info(`init task ${task.name}`);
            await this.addOrUpdate(task);
          }
        }
      }
    }, 3000);
  }
  async initTaskbyTb() {
    const intervalTime = await this.doupiaopiaoSettingEntity.findOneBy({
      model_name: 'tbTime',
    });
    const stepTime = await this.doupiaopiaoSettingEntity.findOneBy({
      model_name: 'stepTime',
    });
    const sessionKey = await this.doupiaopiaoSettingEntity.findOneBy({
      model_name: 'sessionKey',
    });
    console.log(sessionKey.otherValue, 'sessionKey');
    // return;

    // return;
    setInterval(async () => {
      const nowTime = new Date(); // 获取当前时间
      // 计算当前时间前的十分钟
      const tenMinutesAgo = nowTime.getTime() - stepTime.val_data * 60 * 1000;
      const startTime = moment(tenMinutesAgo).format('yyyy-MM-DD HH:mm:ss');
      const endTime = moment(nowTime).format('yyyy-MM-DD HH:mm:ss');
      console.log(startTime, endTime);
      const res = await this.taoBaoRequestService.getTbList(
        {},
        startTime,
        endTime,
        sessionKey.otherValue
      );
      console.log(res);
      if (!res.total_results) {
        return;
      }
      const TbList = res.trades.trade; // 获取淘宝所有的订单
      // console.log(TbList, 'TbList');

      // console.log(TbList);

      // 获取芒果订单和淘宝绑定用户
      const mgRes = await this.doupiaopiaoOrderEntity.find(); // 获取芒果的所有订单
      const userRes = await this.doupiaopiaoUserEntity.find({ tbOpenid: true }); // 获取所有的淘宝绑定用户

      for (const user of userRes) {
        const userTbOrders = TbList.filter(
          tbItem => tbItem.buyer_open_uid === user.tbOpenid
        );

        for (const tbItem of userTbOrders) {
          console.log(tbItem.orders.order, 'tbItem');

          const existingData = await this.doupiaopiaoTblistEntity.findOneBy({
            tborderId: tbItem.tid,
          });

          if (existingData) {
            // 如果已存在相同 tborderId 的数据，可以在此处执行更新操作
            existingData.status = tbItem.status;
            existingData.tbTotalMoney = tbItem.payment;
            existingData.tb_skuid = tbItem.orders.order[0].sku_id;
            existingData.tb_title = tbItem.orders.order[0].title;
            existingData.tb_price = tbItem.orders.order[0].price;
            existingData.tb_num = tbItem.orders.order[0].num;
            existingData.buyer_open_id = tbItem.buyer_open_uid;
            existingData.userId = user.id.toString(); // 将用户ID关联到淘宝订单

            // 保存更新后的数据到数据库
            await existingData.save();
            // console.log(tbItem, 'tbItemtbItemtbItemtbItem');

            if (
              tbItem.status === 'WAIT_SELLER_SEND_GOODS' &&
              tbItem.payment > 0 &&
              existingData.isSubmit == 0
            ) {
              const mgOrder = mgRes.find(
                mgItem =>
                  mgItem.userId == user.id && mgItem.dyPayOrderNo === tbItem.tid
              );

              if (mgOrder) {
                console.log(mgOrder, 'mgOrdermgOrder');
                const createRes = await this.mangoOrderService.createOrder({
                  tel: mgOrder.userPhone,
                  room_id: mgOrder.scheduleId,
                  film_id: mgOrder.movieId,
                  film_code: mgOrder.filmCode,
                  seat_data: JSON.stringify(mgOrder.seatData),
                });
                console.log(
                  createRes,
                  '-------------------createRes==========================='
                );

                mgOrder.userId = user.id.toString();
                mgOrder.orderNo = createRes.data.order_info.order_number;
                mgOrder.normalPayAmount = createRes.data.final_price;
                mgOrder.quickPayAmount = createRes.data.rule_price;
                mgOrder.originalPrice = createRes.data.maoyan_price;
                mgOrder.ticketNum = createRes.data.ticket_num;
                mgOrder.allowChangeSeat = createRes.data.auto_check_seat;
                mgOrder.userPhone = createRes.data.tel;
                mgOrder.movieId = createRes.data.film_id;
                mgOrder.cinemaLineId = createRes.data.line_id;
                mgOrder.cityId = createRes.data.cinemainfo.city_id;
                mgOrder.cinemaId = createRes.data.cinemaid;
                mgOrder.cinemaCode = createRes.data.cinemainfo.cinema_code;
                mgOrder.scheduleId = createRes.data.room_id;
                mgOrder.startTime = createRes.data.roominfo.show_time;
                mgOrder.duration = Number(createRes.data.roominfo.duration);
                mgOrder.movieName = createRes.data.filminfo.name;
                mgOrder.cityName = createRes.data.city;
                mgOrder.cinemaName = createRes.data.cinemainfo.cinema_name;
                mgOrder.cinemaAddres = createRes.data.cinemainfo.cinema_addr;
                mgOrder.hallName = createRes.data.roominfo.hall_name;
                mgOrder.scheduleDesc = createRes.data.show_version_type;
                mgOrder.moviePoster = createRes.data.filminfo.pic;
                mgOrder.seatData = createRes.data.seatdata;
                mgOrder.isQuick = createRes.data.fast_if;
                mgOrder.orderProgress = 1;
                mgOrder.payStatus = 1;
                await mgOrder.save();

                const confirmRes = await this.mangoOrderService.confirmOrder({
                  // mgOrder.orderNo
                  order_number: mgOrder.orderNo,
                  auto_check_seat: mgOrder.allowChangeSeat,
                  fast_buy: mgOrder.isQuick ? 1 : 0,
                });

                if (confirmRes.code == 1) {
                  existingData.isSubmit = 1;
                  await existingData.save();
                }
              }
            }
          } else {
            // 如果不存在相同 tborderId 的数据，执行添加操作
            const data = {
              tborderId: tbItem.tid,
              status: tbItem.status,
              tbTotalMoney: tbItem.payment,
              tb_skuid: tbItem.orders.order[0].sku_id,
              tb_title: tbItem.orders.order[0].title,
              tb_price: tbItem.orders.order[0].price,
              tb_num: tbItem.orders.order[0].num,
              buyer_open_id: tbItem.buyer_open_uid,
              userId: user.id, // 将用户ID关联到淘宝订单
              // 其他字段...
            };

            // 保存淘宝订单信息到 TbOrder 模型中
            await this.doupiaopiaoTblistEntity.save(data);
          }
        }
      }

      // 遍历绑定的用户
      for (const user of userRes) {
        // 获取该用户的淘宝订单
        const userTbOrders = TbList.filter(
          tbItem => tbItem.buyer_open_uid === user.tbOpenid
        );

        if (userTbOrders.length) {
          // 获取该用户尚未绑定的最新的淘宝订单
          const latestTbOrder = userTbOrders.find(
            tbOrder =>
              !mgRes.some(mgOrder => mgOrder.dyPayOrderNo === tbOrder.tid)
          );

          if (latestTbOrder) {
            const mgOrder = mgRes.find(
              mgItem => mgItem.userId == user.id && !mgItem.dyPayOrderNo
            );
            // console.log(mgOrder, 'mgOrdermgOrdermgOrder');

            if (mgOrder) {
              mgOrder.dyPayOrderNo = latestTbOrder.tid;

              // 保存更新后的数据到数据库
              await mgOrder.save();
            }

            // 判断淘宝订单的状态和支付情况
            if (
              latestTbOrder.status === 'WAIT_SELLER_SEND_GOODS' &&
              latestTbOrder.payment > 0
            ) {
              // 绑定最新的淘宝订单信息到相关联的芒果订单
              const mgOrder = mgRes.find(
                mgItem => mgItem.userId == user.id && !mgItem.dyPayOrderNo
              );

              if (mgOrder) {
                const createRes = await this.mangoOrderService.createOrder({
                  tel: mgOrder.userPhone,
                  room_id: mgOrder.scheduleId,
                  film_id: mgOrder.movieId,
                  film_code: mgOrder.filmCode,
                  seat_data: JSON.stringify(mgOrder.seatData),
                });

                mgOrder.userId = user.id.toString();
                mgOrder.orderNo = createRes.data.order_info.order_number;
                mgOrder.normalPayAmount = createRes.data.final_price;
                mgOrder.quickPayAmount = createRes.data.rule_price;
                mgOrder.originalPrice = createRes.data.maoyan_price;
                mgOrder.ticketNum = createRes.data.ticket_num;
                mgOrder.allowChangeSeat = createRes.data.auto_check_seat;
                mgOrder.userPhone = createRes.data.tel;
                mgOrder.movieId = createRes.data.film_id;
                mgOrder.cinemaLineId = createRes.data.line_id;
                mgOrder.cityId = createRes.data.cinemainfo.city_id;
                mgOrder.cinemaId = createRes.data.cinemaid;
                mgOrder.cinemaCode = createRes.data.cinemainfo.cinema_code;
                mgOrder.scheduleId = createRes.data.room_id;
                mgOrder.startTime = createRes.data.roominfo.show_time;
                mgOrder.duration = Number(createRes.data.roominfo.duration);
                mgOrder.movieName = createRes.data.filminfo.name;
                mgOrder.cityName = createRes.data.city;
                mgOrder.cinemaName = createRes.data.cinemainfo.cinema_name;
                mgOrder.cinemaAddres = createRes.data.cinemainfo.cinema_addr;
                mgOrder.hallName = createRes.data.roominfo.hall_name;
                mgOrder.scheduleDesc = createRes.data.show_version_type;
                mgOrder.moviePoster = createRes.data.filminfo.pic;
                mgOrder.seatData = createRes.data.seatdata;
                mgOrder.isQuick = createRes.data.fast_if;
                mgOrder.orderProgress = 1;
                mgOrder.payStatus = 1;

                // 保存更新后的订单信息到数据库
                await mgOrder.save();

                // 根据支付状态更新订单状态
                console.log(mgOrder);
                const confirmRes = await this.mangoOrderService.confirmOrder({
                  order_number: mgOrder.orderNo,
                  auto_check_seat: mgOrder.allowChangeSeat,
                  fast_buy: mgOrder.isQuick ? 1 : 0,
                });
                if (confirmRes.code == 1) {
                  latestTbOrder.isSubmit = 1;
                  await latestTbOrder.save();
                }
              }
            }
          }
        }
      }
    }, Number(intervalTime.val_data));
  }

  async TestByTaoBao() {
    const intervalTime = await this.doupiaopiaoSettingEntity.findOneBy({
      model_name: 'tbTime',
    });
    const stepTime = await this.doupiaopiaoSettingEntity.findOneBy({
      model_name: 'stepTime',
    });
    const sessionKey = await this.doupiaopiaoSettingEntity.findOneBy({
      model_name: 'sessionKey',
    });
    console.log(sessionKey.otherValue, 'sessionKey');

    setInterval(async () => {
      const res = await this.taoBaoRequestService.getTbTest(
        {},
        sessionKey.otherValue,
        '3575184303256535846'
      );
      console.log(res, '1111111111111111111111');
    }, 10000);
  }
  // ______________________________________________随机生成票码
  async savedCard() {
    // return

    const numberOfCodes = 100; // 生成100个不重复的兑换码
    const generatedCodes = this.generateUniqueCodes(numberOfCodes);

    console.log('Generated Codes:');
    console.log(generatedCodes);
    for (const code of generatedCodes) {
      const data = {
        userId: 0, // 替换成实际的用户ID
        cardNumber: code.toString(),
        state: 0,
        cardType: 1,
        cardName: '兑换码',
        cardValue: 50,
      };
      await this.doupiaopiaoCarmiEntity.save(data);
    }
  }
  generateRandomCode(length) {
    let result = '';
    const characters =
      '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';

    for (let i = 0; i < length; i++) {
      const randomIndex = Math.floor(Math.random() * characters.length);
      result += characters.charAt(randomIndex);
    }

    return result;
  }

  generateUniqueCodes(count) {
    const codes = new Set(); // 使用Set来存储唯一的兑换码

    while (codes.size < count) {
      const timestamp = process.hrtime.bigint(); // 获取纳秒级时间戳
      const randomPart = this.generateRandomCode(3); // 生成3位随机数
      const code = timestamp + randomPart;

      codes.add(code.toString()); // 添加到Set中，确保唯一性
    }

    return Array.from(codes); // 转换Set为数组并返回
  }
  // ______________________________________________随机生成票码
  /**
   * 任务ID
   * @param jobId
   */
  async getNextRunTime(jobId) {
    let nextRunTime;
    const result = await this.taskInfoQueue.getRepeatableJobs();
    const task = _.find(result, { id: jobId + '' });
    if (task) {
      nextRunTime = new Date(task.next);
    }
    return nextRunTime;
  }
  /**
   * 更新下次执行时间
   * @param jobId
   */
  async updateNextRunTime(jobId) {
    await this.nativeQuery(
      'update task_info a set a.nextRunTime = ? where a.id = ?',
      [await this.getNextRunTime(jobId), jobId]
    );
  }

  /**
   * 详情
   * @param id
   * @returns
   */
  async info(id: any): Promise<any> {
    const info = await this.taskInfoEntity.findOneBy({ id });
    return {
      ...info,
      repeatCount: info.limit,
    };
  }

  /**
   * 刷新任务状态
   */
  async updateStatus(jobId) {
    const result = await this.taskInfoQueue.getRepeatableJobs();
    const job = _.find(result, { id: jobId + '' });
    if (!job) {
      return;
    }
    const task = await this.taskInfoEntity.findOneBy({ id: job.id });
    const nextTime = await this.getNextRunTime(task.id);
    if (task) {
      if (task.nextRunTime.getTime() == nextTime.getTime()) {
        task.status = 0;
        task.nextRunTime = nextTime;
        this.taskInfoQueue.removeRepeatableByKey(job.key);
      } else {
        task.nextRunTime = nextTime;
      }
      await this.taskInfoEntity.update(task.id, task);
    }
  }

  /**
   * 调用service
   * @param serviceStr
   */
  async invokeService(serviceStr) {
    if (serviceStr) {
      const arr = serviceStr.split('.');
      const service = await this.app.getApplicationContext().getAsync(arr[0]);
      for (const child of arr) {
        if (child.includes('(')) {
          const lastArr = child.split('(');
          const param = lastArr[1].replace(')', '');
          if (!param) {
            return service[lastArr[0]]();
          } else {
            return service[lastArr[0]](JSON.parse(param));
          }
        }
      }
    }
  }
}
